package Day012_多线程2.demo01_synchronized关键字;

/**
 * @author zhangyan
 * @date 2020/4/30 9:33
 */
/*
    之前的AtomicInteger类只能保证"变量"的原子性操作，而对多行代码进行"原子性"操作，使用AtomicInteger类就不能达到效果了。


    电影院要卖票，我们模拟电影院的卖票过程。假设要播放的电影是 “葫芦娃大战奥特曼”，本次电影的座位共
    100个(本场电影只能卖100张票)。
    我们来模拟电影院的售票窗口，实现多个窗口同时卖(多个窗口一起卖这100张票)需要窗口，采用线程对象来模拟；需要票，Runnable接口子类来模拟。

    线程安全问题都是由全局变量及静态变量引起的。而每个线程操作这个变量都需要很多步骤：获取变量的
    值、打印变量的值、更改变量的值，而一个线程在执行某一步骤时都可能被暂停，而另一个线程会执行，这
    同样会导致多个线程访问同一个变量，最终导致这个变量的值不准确。
 */
public class demo01_Test {
    public static void main(String[] args) {
        //创建线程任务对象
        MyRunnable ticket = new MyRunnable();
        //创建三个窗口对象
        Thread t1 = new Thread(ticket, "窗口1");
        Thread t2 = new Thread(ticket, "窗口2");
        Thread t3 = new Thread(ticket, "窗口3");
        //同时卖票
        t1.start();
        t2.start();
        t3.start();
    }
}

/*
        测试类：
            结果中有一部分这样现象：
            发现程序出现了两个问题：
            1. 相同的票数,比如5这张票被卖了两回。
            2. 不存在的票，比如0票与-1票，是不存在的。
            这种问题，几个窗口(线程)票数不同步了，这种问题称为线程不安全。
            线程安全问题都是由全局变量及静态变量引起的。而每个线程操作这个变量都需要很多步骤：获取变量的
            值、打印变量的值、更改变量的值，而一个线程在执行某一步骤时都可能被暂停，而另一个线程会执行，这
            同样会导致多个线程访问同一个变量，最终导致这个变量的值不准确。
*/

class MyRunnable implements Runnable {
     int ticket = 100;
/*
  * 执行卖票操作
  */

    public void run() {
        //每个窗口卖票的操作
        //死循环卖票
        while (true) {
            //票卖完,就结束循环
            if (ticket < 1) {
                break;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //获取当前线程对象的名字
            String name = Thread.currentThread().getName();
            System.out.println(name + "正在卖:" + ticket + "张票");
            ticket--;
        }
    }
}